// src/main/java/com/techchat/backend/websocket/ChatWebSocketHandler.java
package com.techchat.backend.websocket;

import com.techchat.backend.mapper.MessageMapper;
import com.techchat.backend.model.Message;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.*;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;

@Component
public class ChatWebSocketHandler extends TextWebSocketHandler {

    // 保存所有已连接的 WebSocketSession
    private final Set<WebSocketSession> sessions = Collections.synchronizedSet(new HashSet<>());

    // 注入 MessageMapper 或者直接注入 MessageService 都可，这里示例注入 Mapper
    private final MessageMapper messageMapper;

    public ChatWebSocketHandler(MessageMapper messageMapper) {
        this.messageMapper = messageMapper;
    }

    /**
     * 建立连接时，将 session 加入 sessions 集合
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        sessions.add(session);
        // （如果需要在新连接时发送历史消息给该 session，可在这里实现）
        // sendHistoryToSession(session);
    }

    /**
     * 接收到客户端发来的消息时，先持久化到数据库，再广播给所有在线客户端
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage textMessage) throws Exception {
        String payload = textMessage.getPayload();
        // 假设前端传来的 payload 是 JSON 字符串，结构类似：
        // {"content":"Hello","sender":"Alice","timestamp":"2025-06-02T03:30:00"}

        // 将 JSON 解析成 Message 对象（可用 Jackson 或手动解析）
        // 这里示例使用简单字符串拼接解析，仅供示意，生产应用请使用 ObjectMapper
        // 例如 payload = "{\"content\":\"Hello\",\"sender\":\"Alice\",\"timestamp\":\"2025-06-02T03:30:00\"}"
        Message msg = parseJsonToMessage(payload);

        // 1. 将消息插入数据库：注意 Mapper 方法名为 insertMessage，而非 insert
        messageMapper.insertMessage(msg);

        // 2. 将消息广播给所有在线客户端
        broadcastToAllSessions(msg);
    }

    /**
     * 连接关闭时从 sessions 中移除
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        sessions.remove(session);
    }

    /**
     * 将 Message 对象转换为 TextMessage 并推送给所有在线 session
     */
    private void broadcastToAllSessions(Message msg) {
        // 将 Message 对象转回 JSON 格式字符串
        String json = messageToJson(msg);

        synchronized (sessions) {
            for (WebSocketSession ws : sessions) {
                if (ws.isOpen()) {
                    try {
                        ws.sendMessage(new TextMessage(json));
                    } catch (IOException e) {
                        // 某些会话发送失败时，可以打印日志或移除该 session
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * 示例：把 JSON 字符串解析为 Message 对象
     * 实际项目建议用 Jackson 的 ObjectMapper 来做反序列化
     */
    private Message parseJsonToMessage(String payload) {
        // 这里只做简化演示，请根据你前端发送的实际格式修改
        // 假设前端发来的 payload 请和 Jackson 约定格式：
        // {"content":"...","sender":"...","timestamp":"2025-06-02T03:30:00"}
        String content = extractField(payload, "content");
        String sender = extractField(payload, "sender");
        String timestampStr = extractField(payload, "timestamp");

        Message msg = new Message();
        msg.setContent(content);
        msg.setSender(sender);
        // 将字符串 parse 为 LocalDateTime
        msg.setTimestamp(LocalDateTime.parse(timestampStr));
        return msg;
    }

    /**
     * 示例：将 Message 对象转换为 JSON 字符串
     * 实际项目中建议用 Jackson 的 ObjectMapper
     */
    private String messageToJson(Message msg) {
        // 简单拼接 JSON，生产项目请使用更严谨的方式
        return String.format(
                "{\"id\":%d,\"content\":\"%s\",\"sender\":\"%s\",\"timestamp\":\"%s\"}",
                msg.getId(),
                msg.getContent().replace("\"", "\\\""),
                msg.getSender(),
                msg.getTimestamp().toString()
        );
    }

    /**
     * 从简单 JSON 片段里提取字段值（仅做示例），不要用于生产环境
     */
    private String extractField(String json, String fieldName) {
        String pattern = "\"" + fieldName + "\":\"";
        int start = json.indexOf(pattern);
        if (start < 0) {
            return "";
        }
        start += pattern.length();
        int end = json.indexOf("\"", start);
        if (end < 0) {
            return "";
        }
        return json.substring(start, end);
    }
}
